package com.geqian.web.utils;

import org.lionsoul.ip2region.xdb.Searcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


/**
 * <dependency>
 * <groupId>org.lionsoul</groupId>
 * <artifactId>ip2region</artifactId>
 * <version>2.6.5</version>
 * </dependency>
 */
public class IpUtils {

    private static final Logger log = LoggerFactory.getLogger(IpUtils.class);

    private static Searcher searcher;

    static {
        try {
            String dbPath = Objects.requireNonNull(IpUtils.class.getClassLoader().getResource("ipdb/ip2region.xdb")).getPath();
            byte[] bytes = Searcher.loadContentFromFile(dbPath);
            searcher = Searcher.newWithBuffer(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static String getIpAddress(HttpServletRequest request) {
        String ipAddress = "";
        try {
            // 以下两个获取在k8s中，将真实的客户端IP，放到了x-Original-Forwarded-For。而将WAF的回源地址放到了 x-Forwarded-For了。
            ipAddress = request.getHeader("X-Original-Forwarded-For");
            if (ipAddress == null || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("X-Forwarded-For");
            }

            // 获取nginx等代理的ip
            if (ipAddress == null || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("x-forwarded-for");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ipAddress == null || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
            }

            // 如果没有转发的ip，则取当前通信的请求端的ip(兼容k8s集群获取ip)
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                // 如果是127.0.0.1，则取本地真实ip
                if ("127.0.0.1".equals(ipAddress) || "0:0:0:0:0:0:0:1".equals(ipAddress)) {
                    try {
                        // 根据网卡取本机配置的IP
                        InetAddress inet = InetAddress.getLocalHost();
                        ipAddress = inet.getHostAddress();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                }
            }
            // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
            if (ipAddress != null && ipAddress.length() > 15) {
                // = 15
                if (ipAddress.indexOf(",") > 0) {
                    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                }
            }
        } catch (Exception e) {
            log.error("解析请求IP失败", e);
        }
        return "0:0:0:0:0:0:0:1".equals(ipAddress) ? "127.0.0.1" : ipAddress;
    }


    /**
     * 获取IP归属地
     *
     * @param ip
     * @return
     */
    public static String getLocation(String ip) {
        Map<String, String> information = parseIp(ip);
        if ("中国".equals(information.get("country"))) {
            //国内属地返回省份
            return information.get("province") + " " + information.get("city");
        } else if (Objects.equals("", information.get("country"))) {
            //内网 IP
            return "";
        } else {
            //国外属地返回国家
            return information.get("country");
        }
    }

    /**
     * 解析IP地址
     *
     * @param ip
     * @return
     */
    public static Map<String, String> parseIp(String ip) {
        Map<String, String> information = new HashMap<>(6);
        try {
            String source = searcher.search(ip);
            if (source != null && !Objects.equals("", source.trim())) {
                String[] elements = source.split("\\|");
                information.put("country", elements[0]);
                information.put("regionCode", elements[1]);
                information.put("province", elements[2]);
                information.put("city", elements[3]);
                information.put("isp", elements[4]);
                information.put("ip", ip);
            }
            return information;
        } catch (Exception e) {
            e.printStackTrace();
            return information;
        }
    }


    /**
     * 解析IP地址
     *
     * @param request
     * @return
     */
    public static Map<String, String> parseIp(HttpServletRequest request) {
        Map<String, String> information = new HashMap<>(6);
        try {
            String ip = getIpAddress(request);
            if (isInternalIp(ip)) {
                ip = getPublicIp();
            }
            String source = searcher.search(ip);
            if (source != null && !Objects.equals("", source.trim())) {
                String[] elements = source.split("\\|");
                information.put("country", elements[0]);
                information.put("regionCode", elements[1]);
                information.put("province", elements[2]);
                information.put("city", elements[3]);
                information.put("isp", elements[4]);
                information.put("ip", ip);
            }
            return information;
        } catch (Exception e) {
            log.info("IP解析失败,{}", e.getMessage());
            return information;
        }
    }


    /**
     * 获取公网IP
     *
     * @return
     */
    public static String getPublicIp() {
        try {
            URL url = new URL("https://ipv4.icanhazip.com/");
            BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
            String publicIp = reader.readLine().trim();
            if (!Objects.equals(publicIp.trim(), "")) {
                return publicIp;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 获取主机名
     */
    public static String getHostName() {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
            e.printStackTrace();
            return "未知";
        }
    }


    /**
     * 获取本地IP地址
     */
    public static String getHostIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
            return "未知";
        }
    }

    /**
     * 是否是内网IP
     *
     * @param ip
     * @return
     * @throws UnknownHostException
     */
    private static boolean isInternalIp(String ip) throws UnknownHostException {
        InetAddress inetAddress = InetAddress.getByName(ip);
        return inetAddress.isSiteLocalAddress();
    }

}
